import { InjectRepository } from '@nestjs/typeorm'
import { Injectable } from '@nestjs/common'
import * as WebSocket from 'ws'
import { Socket } from './socket.entity'
import { Repository } from 'typeorm'
import * as CryptoJS from 'crypto-js'

@Injectable()
export class SocketService {
  constructor(@InjectRepository(Socket) public socket: Repository<Socket>) {}

  async getList() {
    return await this.socket.find({})
  }

  async findOne({ port, host }) {
    return await this.socket.findOne({
      port,
      host
    })
  }

  async getLatest() {
    const list = await this.socket.find({})
    if (list) {
      return list[list.length - 1]
    } else {
      return null
    }
  }

  async createNext({ host, port }) {
    let prevSocket = await this.getLatest()
    const nextSocket = new Socket()
    nextSocket.host = host
    nextSocket.port = port
    nextSocket.timestamp = new Date().getTime() / 1000
    if (prevSocket) {
      nextSocket.prevHash = prevSocket.hash
      nextSocket.hash = this.calculateHash({
        host,
        port,
        prevHash: nextSocket.prevHash,
        timestamp: nextSocket.timestamp
      })
      await this.socket.insert(nextSocket)
      return nextSocket
    } else {
      nextSocket.prevHash = '0'
      nextSocket.hash = this.calculateHash({
        host,
        port,
        prevHash: nextSocket.prevHash,
        timestamp: nextSocket.timestamp
      })
      await this.socket.insert(nextSocket)
      return nextSocket
    }
  }

  private calculateHash({ host, port, prevHash, timestamp }) {
    const str = `${host}${port}${prevHash}${timestamp}${Math.random()}`
    return CryptoJS.SHA256(str).toString()
  }

  async checkExist({ host, port }) {
    const item = await this.socket.findOne({
      host,
      port
    })
    if (!item) {
      await this.createNext({
        port,
        host
      })
    }
  }

  async create(host: string, port: number) {
    this.checkExist({ host, port })
    const item = await this.socket.findOne({
      host,
      port
    })
    if (item && item['status'] === 1) {
      // 创建socket
      const socket = new WebSocket.Server(
        {
          host: host,
          port: port
        },
        () => {
          console.log('创建成功')
        }
      )
      socket.on('connection', () => {
        console.log('connection')
      })
      socket.on('error', () => {
        this.socket.update(
          {
            hash: item.hash
          },
          { status: 1 }
        )
        console.log('error')
      })
      socket.on('headers', () => {
        console.log('headers')
      })
      socket.on('listening', () => {
        this.socket.update(
          {
            hash: item.hash
          },
          { status: 2 }
        )
        console.log('listening')
      })
      socket.on('message', () => {
        console.log('message')
      })
      return socket
    }
  }
}
